"""结合因子值生成因子分析报告md文件"""
import os

import matplotlib
import pandas as pd


from module.dynamic_module.factor_analysis.model import FactorAnalysisModel
import copy
from conf import conf
from core.constant import *
from mdutils.mdutils import MdUtils

from tools.researcher import PlanPLT

import matplotlib.pyplot as plt
import matplotlib as mpl

# 设置中文字体为SimHei
mpl.rcParams['font.sans-serif'] = ['SimHei']
# 设置负号正常显示
mpl.rcParams['axes.unicode_minus'] = False

matplotlib.use("Agg")


class FactorSummary:
    def __init__(self, parent):
        self.parent = parent
        if isinstance(self.parent, FactorAnalysisModel):
            pass
        else:
            raise ValueError("模块传入错误！")
        if not self.parent.market_factor_data_df_dc:
            raise ValueError("行情因子数据为空。")
        else:
            pass
        pass

    def factor_plan_1(self):
        result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FA.value,
                                       self.parent.result_folder)
        md_file_path = os.path.join(result_dir_path, "factor_plan1.md")

        md_file = MdUtils(file_name=md_file_path)
        md_file.new_header(1, "一、简单因子分析报告（plan 1）")
        code_content = "DDQ 框架默认的因子报告展示方案，用于将多个因子归一化后在一张图表展示特征。作者可通过在框架内定位factor_plan_1函数的位置，并在所属类最后新增属于自己的研究方案。"
        md_file.insert_code(code_content)
        plan_plt = PlanPLT(self.parent)
        for i, (symbol, market_factor_data_df) in enumerate(self.parent.market_factor_data_df_dc.items()):
            md_file.write("\n---")
            md_file.new_header(2, f"1.{i+1} {symbol}因子特征描述")
            md_file.write("\n---")
            md_file.new_header(3, f"1.{i+1}.1 因子可视化")
            factor_ls = []
            for col in market_factor_data_df.columns:
                if col not in conf.KChart.not_factor_ls.value:
                    factor_ls.append(col)
            # 绘制分布图
            image_syntax = plan_plt.create_and_save_plot(market_factor_data_df, "Profile", factor_ls, result_dir_path, symbol)

            # 添加图片引用
            md_file.new_line()
            md_file.write(image_syntax)

            # 绘制从小到大排列图
            image_syntax = plan_plt.create_and_save_plot(market_factor_data_df, "Density", factor_ls, result_dir_path, symbol)
            # 添加图片引用
            md_file.new_line()
            md_file.write(image_syntax)
            # 绘制频率分布直方图
            image_syntax = plan_plt.create_and_save_plot(market_factor_data_df, "Frequency", factor_ls, result_dir_path, symbol)
            # 添加图片引用
            md_file.new_line()
            md_file.write(image_syntax)
            # 添加文字说明
            md_file.write("\n---")
            md_file.new_header(3, f"1.{i + 1}.2 基本特征表")
            describe_df = market_factor_data_df[factor_ls].describe().round(4)
            tab_str_ls = []
            row = 0
            tab_head = ["--"] + describe_df.columns.tolist()
            tab_str_ls += tab_head
            row += 1
            for index_o in describe_df.index:
                tab_row = [index_o] + describe_df.loc[index_o].astype(str).tolist()
                tab_str_ls += tab_row
                row += 1
            md_file.new_line()
            md_file.new_table(int(len(tab_str_ls) / row), row, tab_str_ls)

        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html

    def factor_plan_2(self):
        market_factor_data_df_dc = self.parent.market_factor_data_df_dc
        result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FA.value,
                                       self.parent.result_folder)
        md_file_path = os.path.join(result_dir_path, "factor_plan2.md")
        # 绘制选股云图
        md_file = MdUtils(file_name=md_file_path)
        md_file.new_header(1, "一、选股云图（plan 2）")
        code_content = "DDQ 框架默认的因子报告展示方案，用于制作选股云图。作者可通过在框架内定位factor_plan_1函数的位置，并在所属类最后新增属于自己的研究方案。"
        md_file.insert_code(code_content)
        # 模拟股票涨跌幅数据
        stocks = {symbol: df.iloc[-1, -1] for symbol, df in market_factor_data_df_dc.items()}


        plan_plt = PlanPLT(self.parent)
        image_syntax = plan_plt.gen_save_fig(stocks, result_dir_path)
        md_file.write("\n---")
        md_file.new_line()
        md_file.write(image_syntax)
        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html
        pass

    def factor_plan_3(self):
        result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FA.value,
                                       self.parent.result_folder)
        md_file_path = os.path.join(result_dir_path, "backtest_plan3.md")
        plan_plt = PlanPLT(self.parent)
        md_file = MdUtils(file_name=md_file_path)
        md_file.new_header(1, "一、剔除极端值相关因子数据（plan 3）")
        code_content = "DDQ 框架默认的因子报告展示方案，用于展示因子特征描述。作者可通过在框架内定位factor_plan_1函数的位置，并在所属类最后新增属于自己的研究方案。"
        md_file.insert_code(code_content)
        for i, (symbol, market_factor_data_df) in enumerate(self.parent.market_factor_data_df_dc.items()):
            md_file.write("\n---")
            md_file.new_header(2, f"1.{i + 1} {symbol}因子特征描述")
            plan_plt.plan3_fig(market_factor_data_df, symbol, result_dir_path, md_file)
        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html

    def factor_plan_4(self):
        result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FA.value,
                                       self.parent.result_folder)
        md_file_path = os.path.join(result_dir_path, "backtest_plan4.md")

        md_file = MdUtils(file_name=md_file_path)
        md_file.new_header(1, "一、因子（连续）自然分布图（plan 4）")
        code_content = "DDQ 框架默认的因子报告展示方案，用于单独展示连续因子自然分布特征。作者可通过在框架内定位factor_plan_1函数的位置，并在所属类最后新增属于自己的研究方案。"
        md_file.insert_code(code_content)

        plan_plt = PlanPLT(self.parent)

        for i, (symbol, market_factor_data_df) in enumerate(self.parent.market_factor_data_df_dc.items()):
            trimmed_df: pd.DataFrame = copy.deepcopy(market_factor_data_df)
            factor_ls = []
            for column in trimmed_df.columns:
                if column not in conf.KChart.not_factor_ls.value:
                    factor_ls.append(column)
            num = 4
            if len(factor_ls) > num:
                info = f"该方案不支持超过{num}个因子的数据。"
                self.parent.master.file_manager.log_engine.emit(info, LogName.Running)
                return
            md_file.write("\n---")
            md_file.new_header(2, f"{i + 1} {symbol}相关")
            md_file.write("\n---")
            md_file.new_header(3, f"{i + 1}.1 {symbol}收盘价")
            # 绘制收盘价图
            image_syntax = plan_plt.plan_distribution_fig(trimmed_df, "close", factor_ls, result_dir_path, symbol)
            md_file.write("\n---")
            md_file.new_line()
            md_file.write(image_syntax)

            md_file.write("\n---")
            md_file.new_header(3, f"{i + 1}.2 {symbol}因子自然分布图")
            # 逐个绘制因子的自然分布图（不缩放）
            image_syntax = plan_plt.plan_distribution_fig(trimmed_df, "factor continuous", factor_ls, result_dir_path, symbol)
            md_file.write("\n---")
            md_file.new_line()
            md_file.write(image_syntax)

        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html

    def factor_plan_5(self):
        """离散因子分析方案"""
        result_dir_path = os.path.join(self.parent.master.file_manager.result_path, ResultFolder.FA.value,
                                       self.parent.result_folder)
        md_file_path = os.path.join(result_dir_path, "backtest_plan5.md")

        md_file = MdUtils(file_name=md_file_path)
        md_file.new_header(1, "一、因子（离散）自然分布图（plan 5）")
        code_content = "DDQ 框架默认的因子报告展示方案，用于单独展示离散因子特征。作者可通过在框架内定位factor_plan_1函数的位置，并在所属类最后新增属于自己的研究方案。"
        md_file.insert_code(code_content)

        plan_plt = PlanPLT(self.parent)

        for i, (symbol, market_factor_data_df) in enumerate(self.parent.market_factor_data_df_dc.items()):
            trimmed_df: pd.DataFrame = copy.deepcopy(market_factor_data_df)
            factor_ls = []
            for column in trimmed_df.columns:
                if column not in conf.KChart.not_factor_ls.value:
                    factor_ls.append(column)
            num = 4
            if len(factor_ls) > num:
                info = f"该方案不支持超过{num}个因子的数据。"
                self.parent.master.file_manager.log_engine.emit(info, LogName.Running)
                return
            md_file.write("\n---")
            md_file.new_header(2, f"{i + 1} {symbol}相关")
            md_file.write("\n---")
            md_file.new_header(3, f"{i + 1}.1 {symbol}收盘价")
            # 绘制收盘价图
            image_syntax = plan_plt.plan_distribution_fig(trimmed_df, "close", factor_ls, result_dir_path, symbol)
            md_file.write("\n---")
            md_file.new_line()
            md_file.write(image_syntax)

            md_file.write("\n---")
            md_file.new_header(3, f"{i + 1}.2 {symbol}因子自然分布图")
            # 逐个绘制因子的自然分布图（不缩放）
            image_syntax = plan_plt.plan_distribution_fig(trimmed_df, "factor dispersed", factor_ls, result_dir_path, symbol)
            md_file.write("\n---")
            md_file.new_line()
            md_file.write(image_syntax)

            md_file.write("\n---")
            md_file.new_header(3, f"{i + 1}.3 {symbol}因子频数分布直方图")
            # 逐个绘制因子的自然分布图（不缩放）
            image_syntax = plan_plt.plan_distribution_fig(trimmed_df, "factor dispersed frequency", factor_ls, result_dir_path,
                                                          symbol)
            md_file.write("\n---")
            md_file.new_line()
            md_file.write(image_syntax)

        self.parent.master.file_manager.save_md(md_file)
        self.parent.master.file_manager.md2html(md_file_path, True)  # 打开html